
using System;
using System.IO;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Globalization;
using System.Diagnostics;
using WeifenLuo.WinFormsUI;
using WeifenLuo.WinFormsUI.Docking;
using ScintillaNet;
using T3K.SketchEditor.Core;
using T3K.SketchEditor.Configuration;

namespace T3K.SketchEditor.Forms
{
	public partial class MainForm : Form {

		#region Constants

		private const string NEW_DOCUMENT_TEXT = "Untitled";
		private const int LINE_NUMBERS_MARGIN_WIDTH = 35; // TODO Don't hardcode this

		#endregion Constants

		#region Fields

		public int _newDocumentCount = 0;
		private string[] _args;
		private int _zoomLevel;
        private EditorManager _editor = EditorManager.Instance;
        private Dictionary<string, SubWindow> _windows = new Dictionary<string, SubWindow>();

		#endregion Fields

        #region class SubWindow
        private class SubWindow {
            string _name;
            Type _type;
            DockContent _instance;
            DockPanel _dockPanel;
            DockState _lastState;
            object[] _parameters;

            public string Name {
                get { return _name; }
            }

            public DockContent Instance {
                get { return _instance; }
            }

            public SubWindow(string name, Type type, DockPanel dockPanel, params object[] parameters) {
                this._name = name;
                this._type = type;
                this._instance = null;
                this._dockPanel = dockPanel;
                this._lastState = DockState.Unknown;
                this._parameters = parameters;
            }

            private object _instanceLocker = new object();
            public void Open() {
                Open(DockState.Unknown);
            }

            public void Open(DockState state) {
                if (_instance == null) {
                    lock (_instanceLocker) {
                        DockContent form = Activator.CreateInstance(_type, _parameters) as DockContent;
                        if (form != null) {
                            form.FormClosed += new FormClosedEventHandler(form_FormClosed);
                            if (state == DockState.Unknown)
                                form.Show(_dockPanel);
                            else
                                form.Show(_dockPanel, state);

                            _instance = form;
                        }
                    }
                } else {
                    _instance.Focus();
                }
            }

            void form_FormClosed(object sender, FormClosedEventArgs e) {
                DockContent form = sender as DockContent;
                if (form != null) {
                    lock (_instanceLocker) {
                        _lastState = form.DockState;
                        form.FormClosed -= new FormClosedEventHandler(form_FormClosed);
                        form.Dispose();
                        form = null;
                        _instance = null;
                    }
                }
            }

            public void Close() {
                lock (_instanceLocker) {
                    _instance.Close();
                    _instance = null;
                }
            }
        }
        #endregion

        #region Properties

        public DocumentForm ActiveDocument
		{
			get
			{
				return dockPanel.ActiveDocument as DocumentForm;
			}
		}

		#endregion Properties

		#region Constructors

		public MainForm()
		{
			// The VS designer doesn't allow the form icon to be specified
			// from a resource, so we'll do it manually here
			this.Icon = Properties.Resources.IconApplication;

			InitializeComponent();

            _editor.RegisterCommands(this, "Main");
            
            MenuConfig menuConfig = MenuConfig.Open("MainMenu");

            MenuStrip mStrip = new MenuStrip();
            menuConfig.BuildMenu(mStrip, new EventHandler(_editor.MainMenu_CallBack));


            this.Controls.Add(mStrip);
            MainMenuStrip = mStrip;

            _editor.InitPlugins();

            //Default windows
            SubWindow debug = new SubWindow("Debug", typeof(OutputForm), dockPanel, "Debug");
            SubWindow output = new SubWindow("Output", typeof(OutputForm), dockPanel, "Output");

            _windows.Add(debug.Name, debug);
            _windows.Add(output.Name, output);

		}

        public void MainMenu_CallBack(object sender, EventArgs args) {

            ToolStripItem item = sender as ToolStripItem;
            if (item != null) {
                string commandDef = item.Tag as string;
                string command = null;
                string parameters = null;
                if (commandDef != null) {
                    string[] commandTokens = commandDef.Split(new char[] { '/' }, 2, StringSplitOptions.RemoveEmptyEntries);
                    if (commandTokens.Length > 0)
                        command = commandTokens[0];
                    if (commandTokens.Length == 2)
                        parameters = commandTokens[1];

                    if (command != null) {
                        if (parameters != null) {
                            _editor.InvokeCommand(item, command, parameters);
                        } else {
                            _editor.InvokeCommand(item, command, string.Empty);
                        }
                    }
                }

            }

        }


		public MainForm(string[] args) : this()
		{
			// Store the command line args
			this._args = args;

			//	I personally really dislike the OfficeXP look on Windows XP with the blue.
			ToolStripProfessionalRenderer renderer = new ToolStripProfessionalRenderer();
			renderer.ColorTable.UseSystemColors = true;
			renderer.RoundedEdges = true;
			ToolStripManager.Renderer = renderer;

			// Set the application title
			Text = Program.Title;
			aboutToolStripMenuItem.Text = String.Format(CultureInfo.CurrentCulture, "&About {0}", Program.Title);
		}

		#endregion Constructors

        #region Commands

        #region Output Commands
        private object debug_OutputLocker = new object();
        private object _outputLocker = new object();

        [Command("Debug.WriteLine")]
        public void Command_DebugWrite(object sender, CommandArgs args) {
            try {
                this.Invoke(new MethodInvoker(delegate() {
                    _windows["Debug"].Open();
                    _editor.InvokeCommand(sender, "Debug.WriteLine", args);
                }));
            } catch { }
            
        }

        [Command("Output.WriteLine")]
        public void Command_OutputWrite(object sender, CommandArgs args) {
            try {
                this.Invoke(new MethodInvoker(delegate() {
                    _windows["Output"].Open();
                    _editor.InvokeCommand(sender, "Output.WriteLine", args);
                }));
            } catch { }
        }
        #endregion

        #region Windows
        [Command("RegisterWindow",
            Desc = "Registers a new type of window in the Editor",
            ParamsDesc = "windowName as string, windowType as Type, &state as DockState, show as Boolean")]
        public void Command_RegisterWindow(object sender, CommandArgs args) {
            
                string windowName = args["Name"] as string;
                Type windowType = args["Type"] as Type;
                DockState state = DockState.Unknown;
                bool show = false;

                if (args.ContainsArg("State", typeof(DockState)))
                    state = (DockState)args["State"];

                if (args.ContainsArg("Show", typeof(bool)))
                    show = (bool)args["Show"];

                SubWindow window = new SubWindow(windowName, windowType, dockPanel);

                if (!_windows.ContainsKey(windowName))
                    _windows.Add(windowName, window);

                if (show) {
                    window.Open(state);
                }
        }

        [Command("Show", 
            Desc = "Show a new form inside the main dock panel (DockPanel)",
            ParamsDesc = "windowName as string")]
        public void Command_WindowShow(object sender, CommandArgs args) {
            string windowName = args["Name"] as string;
            if (windowName != null) {
                if (_windows.ContainsKey(windowName)) {
                    _windows[windowName].Open();
                }
            }
        }
        #endregion

        #region Main Menu
        [Command("GetMenuItem", 
            Desc = "Returns a menu item from the main menu", 
            ParamsDesc = "item as string")]
        public void Command_GetMenuItem(object sender, CommandArgs args) {
            MenuStrip strip = MainMenuStrip as MenuStrip;

            if (strip != null) {
                string sItemDef = args["Item"] as string;
                if (sItemDef != null) {
                    string[] defs = sItemDef.Split(new char[] { '.' }, StringSplitOptions.RemoveEmptyEntries);         
                    foreach (ToolStripItem mItem in strip.Items) {
                        ToolStripItem item = GetMenuItem(defs, mItem, 0);
                        if (item != null) {
                            args.Return.Data = item;
                            return;
                        }
                    }
                }
            }
        }

        private ToolStripItem GetMenuItem(string[] defs, ToolStripItem mItem, int pos) {
            if (defs.Length >= pos + 1) {
                string itemName = defs[pos];

                string name = System.Text.RegularExpressions.Regex.Replace(mItem.Text, "\\W", "");

                if (name == itemName) {

                    if (defs.Length == pos + 1)
                        return mItem;

                    ToolStripMenuItem menuItem = mItem as ToolStripMenuItem;
                    if (menuItem != null) {
                        foreach (ToolStripItem sItem in menuItem.DropDownItems) {
                            ToolStripItem item = GetMenuItem(defs, sItem, pos + 1);
                            if (item != null) {
                                return item;
                            }
                        }
                    }
                }   
            }

            return null;
        }

        [Command("GetMainMenu", Desc = "Returns the application main menustrip")]
        public void Command_GetMainMenu(object sender, CommandArgs args) {
            args.Return.Data = this.MainMenuStrip;
        }
        #endregion

        [Command("NewFile")]
        public void Command_NewDocument(object sender, CommandArgs args) {
            DocumentForm form = NewDocument();
            args.Return.Data = form;
        }

        [Command("OpenFile")]
        public void Command_OpenFile(object sender, CommandArgs args) {

            string filename = null;

            if (args.ContainsArg("FileName")) 
                filename = args["FileName"] as string;

            if (filename != null && filename != string.Empty) {
                args.Return.Data = OpenFile(filename);

                if (args.ContainsArg("LineNum", typeof(int))) {
                    int lineNumber = (int)args["LineNum"];
                    ActiveDocument.Scintilla.GoTo.Line(lineNumber - 1);
                }

            } else
                OpenFile();
        }

        [Command("SaveFile")]
        public void Command_SaveFile(object sender, CommandArgs args) {
            if (ActiveDocument != null)
                ActiveDocument.Save();
        }

        [Command("SaveFileAs")]
        public void Command_SaveFileAs(object sender, CommandArgs args) {
            if (ActiveDocument != null)
                ActiveDocument.SaveAs();
        }

        [Command("SaveAll")]
        public void Command_SaveAll(object sender, CommandArgs args) {
            foreach (DocumentForm doc in dockPanel.Documents) {
                doc.Activate();
                doc.Save();
            }
        }

        [Command("CloseFile")]
        public void Command_CloseFile(object sender, CommandArgs args) {
            if (ActiveDocument != null)
                ActiveDocument.Close();
        }

        [Command("Print")]
        public void Command_Print(object sender, CommandArgs args) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Printing.Print();
        }

        [Command("PrintPreview")]
        public void Command_PrintPreview(object sender, CommandArgs args) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Printing.PrintPreview();
        }

        [Command("ExitApp")]
        public void Command_Exit(object sender, CommandArgs args) {
            Close();
        }

        [Command("Undo")]
        public void Command_Undo(object sender, CommandArgs e) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.UndoRedo.Undo();
        }

        [Command("Redo")]
        public void Command_Redo(object sender, CommandArgs e) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.UndoRedo.Redo();
        }

        [Command("Cut")]
        public void Command_Cut(object sender, CommandArgs e) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Clipboard.Cut();
        }

        [Command("Copy")]
        public void Command_Copy(object sender, CommandArgs e) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Clipboard.Copy();
        }

        [Command("Paste")]
        public void Command_Paste(object sender, CommandArgs e) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Clipboard.Paste();
        }

        [Command("SelectAll")]
        public void Command_SelectAll(object sender, CommandArgs e) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Selection.SelectAll();
        }

        [Command("Find")]
        public void Command_Find(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.FindReplace.ShowFind();
        }

        [Command("Replace")]
        public void Command_Replace(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.FindReplace.ShowReplace();
        }

        [Command("FindInFiles")]
        public void Command_FindInFiles(object sender, CommandArgs e) {
            //	Coming someday...
        }

        [Command("ReplaceInFiles")]
        public void Command_ReplaceInFiles(object sender, CommandArgs e) {
            //	Coming someday...
        }

        [Command("Goto")]
        public void Command_Goto(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.GoTo.ShowGoToDialog();
        }

        [Command("ToggleBookmark")]
        public void Command_ToggleBookmark(object sender, CommandArgs e) {
            Line currentLine = ActiveDocument.Scintilla.Lines.Current;
            if (ActiveDocument.Scintilla.Markers.GetMarkerMask(currentLine) == 0) {
                currentLine.AddMarker(0);
            } else {
                currentLine.DeleteMarker(0);
            }
        }

        [Command("PreviosBookmark")]
        public void Command_PreviosBookmark(object sender, CommandArgs e) {
            //	 I've got to redo this whole FindNextMarker/FindPreviousMarker Scheme
            Line l = ActiveDocument.Scintilla.Lines.Current.FindPreviousMarker(1);
            if (l != null)
                l.Goto();
        }

        [Command("NextBookmark")]
        public void Command_NextBookmark(object sender, CommandArgs e) {
            //	 I've got to redo this whole FindNextMarker/FindPreviousMarker Scheme
            Line l = ActiveDocument.Scintilla.Lines.Current.FindNextMarker(1);
            if (l != null)
                l.Goto();
        }

        [Command("ClearBookmars")]
        public void Command_ClearBookmars(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.Markers.DeleteAll(0);
        }

        [Command("DropMarkers")]
        public void Command_DropMarkers(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.DropMarkers.Drop();
        }

        [Command("CollectMarkers")]
        public void Command_CollectMarkers(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.DropMarkers.Collect();
        }

        [Command("MakeUpperCase")]
        public void Command_MakeUpperCase(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.Commands.Execute(BindableCommand.UpperCase);
        }

        [Command("MakeLowerCase")]
        public void Command_MakeLowerCase(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.Commands.Execute(BindableCommand.LowerCase);
        }

        [Command("CommentStream")]
        public void Command_CommentStream(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.Commands.Execute(BindableCommand.StreamComment);
        }

        [Command("CommentLine")]
        public void Command_CommentLine(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.Commands.Execute(BindableCommand.LineComment);
        }

        [Command("UncommentLine")]
        public void Command_UncommentLine(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.Commands.Execute(BindableCommand.LineUncomment);
        }

        [Command("Autocomplete")]
        public void Command_Autocomplete(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.AutoComplete.Show();
        }

        [Command("InsertSnippet")]
        public void Command_InsertSnippet(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.Snippets.ShowSnippetList();
        }

        [Command("SurroundWith")]
        public void Command_SurroundWith(object sender, CommandArgs e) {
            ActiveDocument.Scintilla.Snippets.ShowSurroundWithList();
        }

        [Command("ToggleToolBar")]
        public void Command_ToggleToolBar(object sender, CommandArgs e) {
            // Toggle the visibility of the tool bar
            toolStrip.Visible = !toolStrip.Visible;
            toolBarToolStripMenuItem.Checked = toolStrip.Visible;
        }

        [Command("ToggleStatusBar")]
        public void Command_ToggleStatusBar(object sender, CommandArgs e) {
            // Toggle the visibility of the status strip
            statusStrip.Visible = !statusStrip.Visible;
            statusBarToolStripMenuItem.Checked = statusStrip.Visible;
        }

        [Command("ToggleWhitespace")]
        public void Command_ToggleWhitespace(object sender, CommandArgs e) {
            // Toggle the whitespace mode for all open files
            whitespaceToolStripMenuItem.Checked = !whitespaceToolStripMenuItem.Checked;
            foreach (DocumentForm doc in dockPanel.Documents) {
                if (whitespaceToolStripMenuItem.Checked)
                    doc.Scintilla.Whitespace.Mode = WhitespaceMode.VisibleAlways;
                else
                    doc.Scintilla.Whitespace.Mode = WhitespaceMode.Invisible;
            }
        }

        [Command("ToggleWordWrap")]
        public void Command_ToggleWordWrap(object sender, CommandArgs e) {
            // Toggle word wrap for all open files
            wordWrapToolStripMenuItem.Checked = !wordWrapToolStripMenuItem.Checked;
            foreach (DocumentForm doc in dockPanel.Documents) {
                if (wordWrapToolStripMenuItem.Checked)
                    doc.Scintilla.LineWrap.Mode = WrapMode.Word;
                else
                    doc.Scintilla.LineWrap.Mode = WrapMode.None;
            }
        }

        [Command("ToggleEndOfLine")]
        public void Command_ToggleEndOfLine(object sender, CommandArgs e) {
            // Toggle EOL visibility for all open files
            endOfLineToolStripMenuItem.Checked = !endOfLineToolStripMenuItem.Checked;
            foreach (DocumentForm doc in dockPanel.Documents) {
                doc.Scintilla.EndOfLine.IsVisible = endOfLineToolStripMenuItem.Checked;
            }
        }

        [Command("ZoomIn")]
        public void Command_ZoomIn(object sender, CommandArgs e) {
            // Increase the zoom for all open files
            _zoomLevel++;
            UpdateAllScintillaZoom();
        }

        [Command("ZoomOut")]
        public void Command_ZoomOut(object sender, CommandArgs e) {
            _zoomLevel--;
            UpdateAllScintillaZoom();
        }

        [Command("ResetZoom")]
        public void Command_ResetZoom(object sender, CommandArgs e) {
            _zoomLevel = 0;
            UpdateAllScintillaZoom();
        }

        [Command("ToggleLineNumbers")]
        public void Command_ToggleLineNumbers(object sender, CommandArgs e) {
            // Toggle the line numbers margin for all documents
            lineNumbersToolStripMenuItem.Checked = !lineNumbersToolStripMenuItem.Checked;
            foreach (DocumentForm docForm in dockPanel.Documents) {
                if (lineNumbersToolStripMenuItem.Checked)
                    docForm.Scintilla.Margins.Margin0.Width = LINE_NUMBERS_MARGIN_WIDTH;
                else
                    docForm.Scintilla.Margins.Margin0.Width = 0;
            }
        }

        [Command("FoldLevel")]
        public void Command_FoldLevel(object sender, CommandArgs e) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Lines.Current.FoldExpanded = true;
        }

        [Command("UnfoldLevel")]
        public void Command_UnfoldLevel(object sender, CommandArgs e) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.Lines.Current.FoldExpanded = false;
        }

        [Command("FoldAll")]
        public void Command_FoldAll(object sender, CommandArgs e) {
            if (ActiveDocument != null) {
                foreach (Line l in ActiveDocument.Scintilla.Lines) {
                    l.FoldExpanded = true;
                }
            }
        }

        [Command("UnfoldAll")]
        public void Command_UnfoldAll(object sender, CommandArgs e) {
            if (ActiveDocument != null) {
                foreach (Line l in ActiveDocument.Scintilla.Lines) {
                    l.FoldExpanded = true;
                }
            }
        }

        [Command("NavigateForward")]
        public void Command_NavigateForward(object sender, CommandArgs e) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.DocumentNavigation.NavigateForward();
        }

        [Command("NavigateBackward")]
        public void Command_NavigateBackward(object sender, CommandArgs e) {
            if (ActiveDocument != null)
                ActiveDocument.Scintilla.DocumentNavigation.NavigateBackward();
        }

        [Command("About")]
        public void Command_About(object sender, CommandArgs e) {
            using (AboutForm aboutForm = new AboutForm())
                aboutForm.ShowDialog(this);
        }

        #endregion

        #region File Menu Handlers

        private void newToolStripMenuItem_Click(object sender, EventArgs e)
		{
			NewDocument();
		}

		private void openToolStripMenuItem_Click(object sender, EventArgs e)
		{
			OpenFile();
		}

		private void saveToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
				ActiveDocument.Save();
		}

		private void saveAsToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
				ActiveDocument.SaveAs();
		}

		private void saveAllStripMenuItem_Click(object sender, EventArgs e)
		{
			foreach (DocumentForm doc in dockPanel.Documents)
			{
				doc.Activate();
				doc.Save();
			}
		}

		private void closeToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
				ActiveDocument.Close();
		}

		private void printToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
				ActiveDocument.Scintilla.Printing.Print();
		}

		private void printPreviewToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
				ActiveDocument.Scintilla.Printing.PrintPreview();
		}

		private void exitToolStripMenuItem_Click(object sender, EventArgs e)
		{
			Close();
		}

		#endregion File Menu Handlers

		#region Edit Menu Handlers

		private void undoToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if(ActiveDocument != null)
				ActiveDocument.Scintilla.UndoRedo.Undo();
		}

		private void redoToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if(ActiveDocument != null)
				ActiveDocument.Scintilla.UndoRedo.Redo();
		}

		private void cutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
				ActiveDocument.Scintilla.Clipboard.Cut();
		}

		private void copyToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
				ActiveDocument.Scintilla.Clipboard.Copy();
		}

		private void pasteToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if(ActiveDocument != null)
				ActiveDocument.Scintilla.Clipboard.Paste();
		}

		private void selectAllToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
				ActiveDocument.Scintilla.Selection.SelectAll();
		}

		private void findToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.FindReplace.ShowFind();
		}

		private void replaceToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.FindReplace.ShowReplace();
		}

		private void findInFilesToolStripMenuItem_Click(object sender, EventArgs e)
		{
			//	Coming someday...
		}

		private void replaceInFilesToolStripMenuItem_Click(object sender, EventArgs e)
		{
			//	Coming someday...
		}

		private void goToToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.GoTo.ShowGoToDialog();
		}

		private void toggleBookmarkToolStripMenuItem_Click(object sender, EventArgs e)
		{
			Line currentLine = ActiveDocument.Scintilla.Lines.Current;
			if (ActiveDocument.Scintilla.Markers.GetMarkerMask(currentLine) == 0)
			{
				currentLine.AddMarker(0);
			}
			else
			{
				currentLine.DeleteMarker(0);
			}
		}

		private void previosBookmarkToolStripMenuItem_Click(object sender, EventArgs e)
		{
			//	 I've got to redo this whole FindNextMarker/FindPreviousMarker Scheme
			Line l = ActiveDocument.Scintilla.Lines.Current.FindPreviousMarker(1);
			if (l != null)
				l.Goto();
		}

		private void nextBookmarkToolStripMenuItem_Click(object sender, EventArgs e)
		{
			//	 I've got to redo this whole FindNextMarker/FindPreviousMarker Scheme
			Line l = ActiveDocument.Scintilla.Lines.Current.FindNextMarker(1);
			if (l != null)
				l.Goto();
		}

		private void clearBookmarsToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.Markers.DeleteAll(0);
		}

		private void dropToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.DropMarkers.Drop();
		}

		private void collectToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.DropMarkers.Collect();
		}

		private void makeUpperCaseToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.Commands.Execute(BindableCommand.UpperCase);
		}

		private void makeLowerCaseToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.Commands.Execute(BindableCommand.LowerCase);
		}

		private void commentStreamToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.Commands.Execute(BindableCommand.StreamComment);
		}

		private void commentLineToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.Commands.Execute(BindableCommand.LineComment);
		}

		private void uncommentLineToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.Commands.Execute(BindableCommand.LineUncomment);
		}

		private void autocompleteToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.AutoComplete.Show();
		}

		private void insertSnippetToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.Snippets.ShowSnippetList();
		}

		private void surroundWithToolStripMenuItem_Click(object sender, EventArgs e)
		{
			ActiveDocument.Scintilla.Snippets.ShowSurroundWithList();
		}

		#endregion Edit Menu Handlers

		#region View Menu Handlers

		private void toolBarToolStripMenuItem_Click(object sender, EventArgs e)
		{
			// Toggle the visibility of the tool bar
			toolStrip.Visible = !toolStrip.Visible;
			toolBarToolStripMenuItem.Checked = toolStrip.Visible;
		}

		private void statusBarToolStripMenuItem_Click(object sender, EventArgs e)
		{
			// Toggle the visibility of the status strip
			statusStrip.Visible = !statusStrip.Visible;
			statusBarToolStripMenuItem.Checked = statusStrip.Visible;
		}


		private void whitespaceToolStripMenuItem_Click(object sender, EventArgs e)
		{
			// Toggle the whitespace mode for all open files
			whitespaceToolStripMenuItem.Checked = !whitespaceToolStripMenuItem.Checked;
			foreach (DocumentForm doc in dockPanel.Documents)
			{
				if (whitespaceToolStripMenuItem.Checked)
					doc.Scintilla.Whitespace.Mode = WhitespaceMode.VisibleAlways;
				else
					doc.Scintilla.Whitespace.Mode = WhitespaceMode.Invisible;
			}
		}

		private void wordWrapToolStripMenuItem_Click(object sender, EventArgs e)
		{
			// Toggle word wrap for all open files
			wordWrapToolStripMenuItem.Checked = !wordWrapToolStripMenuItem.Checked;
			foreach (DocumentForm doc in dockPanel.Documents)
			{
				if (wordWrapToolStripMenuItem.Checked)
					doc.Scintilla.LineWrap.Mode = WrapMode.Word;
				else
					doc.Scintilla.LineWrap.Mode = WrapMode.None;
			}
		}

		private void endOfLineToolStripMenuItem_Click(object sender, EventArgs e)
		{
			// Toggle EOL visibility for all open files
			endOfLineToolStripMenuItem.Checked = !endOfLineToolStripMenuItem.Checked;
			foreach (DocumentForm doc in dockPanel.Documents)
			{
				doc.Scintilla.EndOfLine.IsVisible = endOfLineToolStripMenuItem.Checked;
			}
		}

		private void zoomInToolStripMenuItem_Click(object sender, EventArgs e)
		{
			// Increase the zoom for all open files
			_zoomLevel++;
			UpdateAllScintillaZoom();
		}

		private void zoomOutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			_zoomLevel--;
			UpdateAllScintillaZoom();
		}

		private void resetZoomToolStripMenuItem_Click(object sender, EventArgs e)
		{
			_zoomLevel = 0;
			UpdateAllScintillaZoom();
		}

		private void lineNumbersToolStripMenuItem_Click(object sender, EventArgs e)
		{
			// Toggle the line numbers margin for all documents
			lineNumbersToolStripMenuItem.Checked = !lineNumbersToolStripMenuItem.Checked;
			foreach (DocumentForm docForm in dockPanel.Documents)
			{
				if (lineNumbersToolStripMenuItem.Checked)
					docForm.Scintilla.Margins.Margin0.Width = LINE_NUMBERS_MARGIN_WIDTH;
				else
					docForm.Scintilla.Margins.Margin0.Width = 0;
			}
		}

		private void foldLevelToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if(ActiveDocument != null)
				ActiveDocument.Scintilla.Lines.Current.FoldExpanded = true;
		}

		private void unfoldLevelToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
				ActiveDocument.Scintilla.Lines.Current.FoldExpanded = false;
		}

		private void foldAllToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
			{
				foreach (Line l in ActiveDocument.Scintilla.Lines)
				{
					l.FoldExpanded = true;
				}
			}
		}

		private void unfoldAllToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
			{
				foreach (Line l in ActiveDocument.Scintilla.Lines)
				{
					l.FoldExpanded = true;
				}
			}
		}

		private void navigateForwardToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
				ActiveDocument.Scintilla.DocumentNavigation.NavigateForward();
		}

		private void navigateBackwardToolStripMenuItem_Click(object sender, EventArgs e)
		{
			if (ActiveDocument != null)
				ActiveDocument.Scintilla.DocumentNavigation.NavigateBackward();
		}

		#endregion View Menu Handlers

		#region Language Menu Handlers

		private void cToolStripMenuItem_Click(object sender, EventArgs e)
		{
			SetLanguage("cs");
		}

		private void plainTextToolStripMenuItem_Click(object sender, EventArgs e)
		{
			SetLanguage(String.Empty);
		}

		private void hTMLToolStripMenuItem_Click(object sender, EventArgs e)
		{
			SetLanguage("html");
		}

		private void mSSQLToolStripMenuItem_Click(object sender, EventArgs e)
		{
			SetLanguage("mssql");
		}

		private void vBScriptToolStripMenuItem_Click(object sender, EventArgs e)
		{
			SetLanguage("vbscript");
		}

		private void pythonToolStripMenuItem_Click(object sender, EventArgs e)
		{
			SetLanguage("python");
		}

		private void xMLToolStripMenuItem_Click(object sender, EventArgs e)
		{
			SetLanguage("xml");
		}

		private void iniToolStripMenuItem_Click(object sender, EventArgs e)
		{
			SetLanguage("ini");
		}

		#endregion Language Menu Handlers

		#region Help Menu Handlers

		private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
		{
			using (AboutForm aboutForm = new AboutForm())
				aboutForm.ShowDialog(this);
		}

		#endregion Help Menu Handlers

		#region Misc Handlers

		private void MainForm_Load(object sender, EventArgs e) {
			if (_args != null && _args.Length != 0) {
				// Open the document specified on the command line
				FileInfo fi = new FileInfo(_args[0]);
				if (fi.Exists)
					OpenFile(fi.FullName);
			}
		}

		private void dockPanel_ActiveDocumentChanged(object sender, EventArgs e) {
			// Update the main form text to show the current document
			if(ActiveDocument != null)
				this.Text = String.Format(CultureInfo.CurrentCulture, "{0} - {1}", ActiveDocument.Text, Program.Title);
			else
				this.Text = Program.Title;	
		}

		#endregion Handlers

		#region Methods

		private DocumentForm NewDocument() {
			DocumentForm doc = new DocumentForm();
			SetScintillaToCurrentOptions(doc);
			doc.Text = String.Format(CultureInfo.CurrentCulture, "{0}{1}", NEW_DOCUMENT_TEXT, ++_newDocumentCount);
			doc.Show(dockPanel);
			return doc;
		}

		private void OpenFile() {

			if (openFileDialog.ShowDialog() != DialogResult.OK)
				return;

			foreach (string filePath in openFileDialog.FileNames) {
                OpenFile(filePath); //It Ensures that the file is not already open
			}
		}

		private DocumentForm OpenFile(string filePath) {

            // Ensure this file isn't already open
            foreach (DocumentForm documentForm in dockPanel.Documents) {
                if (filePath.Equals(documentForm.FilePath, StringComparison.OrdinalIgnoreCase)) {
                    documentForm.Activate();

                    documentForm.Select();
                    return documentForm;
                }
            }

            DocumentForm doc = new DocumentForm();
            SetScintillaToCurrentOptions(doc);
            doc.Scintilla.Text = File.ReadAllText(filePath);
            doc.Scintilla.UndoRedo.EmptyUndoBuffer();
            doc.Scintilla.Modified = false;
            doc.Text = Path.GetFileName(filePath);
            doc.FilePath = filePath;
            doc.Show(dockPanel);

            return doc;
            
		}

		private void UpdateAllScintillaZoom()
		{
			// Update zoom level for all files
			foreach (DocumentForm doc in dockPanel.Documents)
				doc.Scintilla.Zoom = _zoomLevel;
		}

		private void SetScintillaToCurrentOptions(DocumentForm doc)
		{
			// Turn on line numbers?
			if (lineNumbersToolStripMenuItem.Checked)
				doc.Scintilla.Margins.Margin0.Width = LINE_NUMBERS_MARGIN_WIDTH;
			else
				doc.Scintilla.Margins.Margin0.Width = 0;

			// Turn on white space?
			if (whitespaceToolStripMenuItem.Checked)
				doc.Scintilla.Whitespace.Mode = WhitespaceMode.VisibleAlways;
			else
				doc.Scintilla.Whitespace.Mode = WhitespaceMode.Invisible;

			// Turn on word wrap?
			if (wordWrapToolStripMenuItem.Checked)
				doc.Scintilla.LineWrap.Mode = WrapMode.Word;
			else
				doc.Scintilla.LineWrap.Mode = WrapMode.None;

			// Show EOL?
			doc.Scintilla.EndOfLine.IsVisible = endOfLineToolStripMenuItem.Checked;

			// Set the zoom
			doc.Scintilla.Zoom = _zoomLevel;
		}

		private void SetLanguage(string language)
		{

				// Use a built-in lexer and configuration
				ActiveDocument.Scintilla.ConfigurationManager.Language = language;
				
				// Smart indenting...
				
                ActiveDocument.Scintilla.Indentation.SmartIndentType = SmartIndent.CPP;
			
				//ActiveDocument.Scintilla.Indentation.SmartIndentType = SmartIndent.None;

		}

		#endregion Methods
	}
}